// 利用高阶函数-将函数作为参数写一个forEach函数
function forEach(arr, fn) {
  for (let i = 0; i < arr.length; i++) {
    fn(arr[i], i)
  }
}
// let arr = [1, 2, 3, 4, 5]
// forEach(arr, (item, index) => {
//   console.log(item, index)
// })

function filter(arr, fn) {
  let result = []
  for (let i = 0; i < arr.length; i++) {
    if (fn(arr[i])) {
      result.push(arr[i])
    }
  }
  return result
}

// let newArr = filter(arr, item => {
//   return item > 3
// })
// console.log(newArr)

// 利用函数可以作为返回值，实现一个once函数-只执行一次
function once(fn) {
  let mark = false
  return function () {
    if (!mark) {
      mark = true
      fn.apply(this, arguments)
    }
  }
}
// let pay = once((money) => {
//   console.log(`${money} RMB`)
// })
// pay(100)
// pay(100)
// pay(100)
// pay(100)


// map
function map(arr, fn) {
  let result = []
  for (let value of arr) {
    result.push(fn(value))
  }
  return result
}

// arr = map([1, 2, 3], i => i * 2)

// every
const every = (arr, fn) => {
  let result = true;
  for (let value of arr) {
    if (!fn(value)) {
      result = false;
      break;
    }
  }
  return result
}
// arr = every([1, 3, 6], v => v < 5)


// some
const some = (arr, fn) => {
  let result = false;
  for (let value of arr) {
    if (fn(value)) {
      result = true;
      break;
    }
  }
  return result
}
// arr = some([1, 2, 3], v => v > 1)
// console.log(arr)


function outter() {
  let num = 0
  return function inner() {
    console.log(num++)
  }
}
// let o = outter()
// o()
// o()
// o()

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// slice 没有修改原数组，每次返回结果一样，是纯函数
// console.log(arr.slice(1, 3))  //[ 2, 3 ]
// console.log(arr.slice(1, 3))  //[ 2, 3 ]
// console.log(arr.slice(1, 3))  //[ 2, 3 ]
// // splice 修改了原数组，每次返回结果不一样，是不纯的函数
// console.log(arr.splice(1, 3)) //[ 2, 3, 4 ]
// console.log(arr.splice(1, 3)) //[ 5, 6, 7 ]
// console.log(arr.splice(1, 3)) //[ 8, 9 ]

const _ = require('lodash')
const array = ['jack', 'dom', 'lucy', 'kate']
// console.log(_.first(array))
// console.log(_.last(array))
// console.log(_.toUpper(_.first(array)))
// console.log(array,000)
// console.log(_.reverse(array))
// console.log(_.reverse(array))
// console.log(array,111)
// const r = _.each(array, item => {
//   console.log(item)
// })
// console.log(r)

// console.log(_.includes(array,'jack'))
// console.log(_.find(array, 'dom'))



// let getAreaWithMemory = _.memoize(getArea)
// console.log(getAreaWithMemory(4))
// console.log(getAreaWithMemory(4))
// console.log(getAreaWithMemory(4))

function getArea(r) {
  console.log(r)
  return Math.PI * r * r
}
function memoize(f) {
  let cache = {}
  return function () {
    let key = JSON.stringify(arguments)
    cache[key] = cache[key] || f.apply(f, arguments)
    return cache[key]
  }
}
let getAreaWithMemory = memoize(getArea)
console.log(getAreaWithMemory(4)) // 4 50.26548245743669
console.log(getAreaWithMemory(4)) // 50.26548245743669
console.log(getAreaWithMemory(5)) // 5 78.53981633974483


// 不纯
// let mini = 18
// function checkAge(age) {
//   return age >= mini
// }
// // 纯的，有硬编码
// function checkAge(age) {
//   let mini = 18
//   return age >= mini
// }

// 普通的纯函数
// function checkAge(min, age) {
//   return age >= min
// }
// console.log(checkAge(18, 20))
// console.log(checkAge(18, 24))
// console.log(checkAge(22, 24))

// function checkAge(min) {
//   return function (age) {
//     return age >= min
//   }
// }
let checkAge = min => (age => age >= min)
let checkAge18 = checkAge(18)
let checkAge20 = checkAge(20)

// console.log(checkAge18(20))
// console.log(checkAge20(24))





function curry(fn) {
  return function a(...args) {
    if (args.length < fn.length) {
      return function () {
        return a(...args.concat(Array.from(arguments)))
      }
    }
    return fn(...args)
  }
}
function getSum(a, b, c) {
  return a + b + c
}
const curried = curry(getSum)
console.log(curried(1, 2, 3))
console.log(curried(1)(2, 3))
console.log(curried(1)(2)(3))